package com.hai;

import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.io.IOException;
import java.lang.ref.WeakReference;

public class LiveActivity extends AppCompatActivity implements SurfaceHolder.Callback, Camera.PreviewCallback {
    private static final String TAG = "LiveActivity";
    private static final int STREAMER_INIT = 0;
    private static final int STREAMER_HANDLE = 1;
    private static final int STREAMER_RELEASE = 2;
    private static final int STREAMER_FLUSH = 3;

    SurfaceView surfaceView;
    SurfaceHolder holder;
    Camera camera;
    int cameraId = 0;
    int width;
    int height;

    HandlerThread mHandlerThread;
    LiveHandler mHandler;
    /**
     * 判断有没有初始化成功，不成功不不进行后续的编码处理
     */
    private int liveInitResult = -1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_live);
        surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
        holder = surfaceView.getHolder();
        holder.addCallback(this);
        mHandlerThread = new HandlerThread("liveHandlerThread");
        mHandlerThread.start();
        mHandler = new LiveHandler(this, mHandlerThread.getLooper());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.switch_camera, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.id_switch) {
            cameraId = cameraId == 0 ? 1 : 0;
            destroyCamera();
            initCamera();
        }
        return super.onOptionsItemSelected(item);
    }

    private void initCamera() {
        camera = Camera.open(cameraId);
        try {
            camera.getNumberOfCameras();
            camera.setPreviewDisplay(holder);
            Camera.Parameters parameters = camera.getParameters();
            parameters.setPreviewFormat(ImageFormat.NV21);
            camera.setDisplayOrientation(90);
            camera.setParameters(parameters);
            camera.setPreviewCallback(this);
            camera.startPreview();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void destroyCamera() {
        if (camera != null) {
            camera.setPreviewCallback(null);
            camera.stopPreview();
            camera.release();
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        width = surfaceView.getMeasuredWidth();
        height = surfaceView.getMeasuredHeight();
        /**
         * 在surface创建的时候进行初始化，如果失败了，也是需要释放已经开辟了的资源
         */
        liveInitResult = streamerInit(width, height);
        Log.i(TAG, "surfaceCreated() called with: width = [" + width + "] height = [" + height + "]");
        if (liveInitResult == -1) {
            mHandler.sendEmptyMessage(STREAMER_RELEASE);
        } else {
            Log.e("LiveActivity", "streamer init result: " + liveInitResult);
        }
        initCamera();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        /**
         * 在surface销毁的时候清空缓冲帧（在直播成功开启的情况下）
         * 清空后就进行资源的释放
         * 并且把HandlerThread退出
         */
        if(liveInitResult == 0) {
            mHandler.sendEmptyMessage(STREAMER_FLUSH);
        }
        mHandler.sendEmptyMessage(STREAMER_RELEASE);
        mHandlerThread.quitSafely();
        destroyCamera();
    }


    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        /**
         * 如果初始化成功，那就把数据发送到Handler，然后再调用native方法
         */
        if (liveInitResult == 0 && data != null && data.length > 0) {
            Message msg = Message.obtain();
            Bundle bundle = new Bundle();
            bundle.putByteArray("frame_data", data);
            msg.what = STREAMER_HANDLE;
            msg.setData(bundle);
            mHandler.sendMessage(msg);
        }
    }

    private static class LiveHandler extends Handler {
        private WeakReference<LiveActivity> mActivity;

        public LiveHandler(LiveActivity activity, Looper looper) {
            super(looper);
            mActivity = new WeakReference(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            LiveActivity activity = mActivity.get();
            if (activity == null) {
                return;
            }

            switch (msg.what) {
                case STREAMER_INIT:
                    break;

                case STREAMER_HANDLE:
                    Bundle bundle = msg.getData();
                    if (bundle != null) {
                        byte[] data = bundle.getByteArray("frame_data");
                        if (data != null && data.length > 0) {
                            activity.streamerHandle(data);
                        } else {
                            Log.e("LiveActivity", "byte data null");
                        }
                    } else {
                        Log.e("LiveActivity", "bundle null");
                    }
                    break;

                case STREAMER_FLUSH:
                    activity.streamerFlush();
                    break;

                case STREAMER_RELEASE:
                    activity.streamerRelease();
                    break;
            }
        }
    }

    /**
     * 初始化编码的一些东西，比如编码器等
     *
     * @param width  编码视频的宽
     * @param height 编码视频的高
     * @return 0 成功  小于0失败
     */
    private native int streamerInit(int width, int height);

    /**
     * 对每一次预览的数据进行编码推流
     *
     * @param data NV21格式的数据
     * @return 0成功，小于0失败
     */
    private native int streamerHandle(byte[] data);

    /**
     * 把缓冲帧的数据清空
     *
     * @return 0成功，小于0失败
     */
    private native int streamerFlush();

    /**
     * 释放资源，比如编码器这些
     *
     * @return 0成功，小于0失败
     */
    private native int streamerRelease();

}
